package com.znf4.controller.util;

import java.io.BufferedInputStream;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.io.UnsupportedEncodingException;
import java.net.URL;
import java.net.URLConnection;
import java.net.URLEncoder;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;

import javax.servlet.http.HttpServletRequest;

import org.apache.log4j.Logger;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.znf4.cache.redis.RedisUtils;
import com.znf4.config.SystemConfig;
import com.znf4.utils.SFTPUtil;
import com.znf4.utils.StringUtil;


/**
 * 微信工具
 *
 */
public class WeixinUtil {
	private static Logger logger = Logger.getLogger(WeixinUtil.class);

	public final static String ENCRYPT_KEY = "N3yMgG4vUvE=";// 加密默认密钥，别改

	// 网页授权地址，静默方式snsapi_base
	private static String oAuthUrl = "https://open.weixin.qq.com/connect/oauth2/authorize?appid=%s&redirect_uri=%s&response_type=code&scope=snsapi_base&state=STATE#wechat_redirect";
	
	//private static String oAuthUrl = "http://llh.huiepay.com/oauth2?appid=%s&redirect_uri=%s&response_type=code&scope=snsapi_base&state=STATE#wechat_redirect";
	
	// http://xxx/wx/auth/authRedirect/%s;
	private static String exchangeTokenUrl = "https://api.weixin.qq.com/sns/oauth2/access_token?appid=%s&secret=%s&code=%s&grant_type=authorization_code";

	/**
	 * 获取网页授权地址，静默方式snsapi_base
	 * 
	 * @param authRedirectUrl
	 *            回调请求路径
	 */
	public static String getoAuthUrlBy_snsapi_base(String authRedirectUrl, String appId) throws UnsupportedEncodingException {
		if (StringUtil.isEmpty(appId)) {
			appId = SystemConfig.WEIXIN_PAY_APP_ID;// 如果没有传appid，直接拿全局的appid
		}
		System.out.println(String.format(oAuthUrl, appId,authRedirectUrl));
		
		return String.format(oAuthUrl, appId, URLEncoder.encode(authRedirectUrl, "UTF-8"));
//		return String.format(oAuthUrl, appId, authRedirectUrl );
	}

	/**
	 * 获取网页授权地址，静默方式snsapi_base(区别公众号，专门为支付配置的公众号ID)
	 * 
	 * @param authRedirectUrl
	 *            回调请求路径
	 */
	public static String getoAuthUrlForPayBy_snsapi_base(String authRedirectUrl, String appId) throws UnsupportedEncodingException {
		if (StringUtil.isEmpty(appId)) {
			appId = SystemConfig.WEIXIN_PAY_APP_ID;
		}
		logger.info("======================>支付授权的appId:" + appId);
//		return String.format(oAuthUrl, appId, URLEncoder.encode(authRedirectUrl, "UTF-8"));
		return String.format(oAuthUrl, appId, authRedirectUrl );
	}

	/**
	 * 请求一个URL并返回JSON内容
	 * 
	 * @param url
	 * @param requestMethod
	 * @return
	 * @throws Exception
	 */
	public static String getJsonFromUrl(String urlAdd, String requestMethod, Map<String, Object> param) {
		InputStreamReader reader = null;
		BufferedReader in = null;
		PrintWriter out = null;
		try {
			URL url = new URL(urlAdd);
			URLConnection connection = url.openConnection();
			if (requestMethod != null && (requestMethod.equals("POST") || requestMethod.equals("post"))) {
				// 发送POST请求必须设置如下两行
				connection.setDoOutput(true);
				connection.setDoInput(true);
				// 获取URLConnection对象对应的输出流
				out = new PrintWriter(connection.getOutputStream());
				// 发送请求参数
				if (param != null) {
					logger.info("======================>param:" + JSON.toJSONString(param));
					out.print(JSON.toJSONString(param));
				}
				// flush输出流的缓冲
				out.flush();
			} else {
				connection.setConnectTimeout(1000);
			}
			reader = new InputStreamReader(connection.getInputStream(), "UTF-8");
			in = new BufferedReader(reader);
			String line = null; // 每行内容
			int lineFlag = 0; // 标记: 判断有没有数据
			StringBuffer content = new StringBuffer();
			while ((line = in.readLine()) != null) {
				content.append(line);
				lineFlag++;
			}
			return lineFlag == 0 ? null : content.toString();
		} catch (Exception e) {
			logger.error("连接超时!!!");
			return null;
		} finally {
			if (out != null) {
				out.close();
			}
			if (in != null) {
				try {
					in.close();
				} catch (IOException e) {
					logger.error("关闭流出现异常!!!");
				}
			}
			if (reader != null) {
				try {
					reader.close();
				} catch (IOException e) {
					logger.error("关闭流出现异常!!!");
				}
			}
		}
	}

	/**
	 * 换取token后，获得openid，公众号的appId和secret
	 * 
	 * @param code
	 *            微信回调返回的code
	 */
	@SuppressWarnings("unchecked")
	public static String getOpenid(String code, String appId, String appSecret) {
		if (StringUtil.isNotNull(code)) {
			String url = String.format(exchangeTokenUrl, appId, appSecret, code);
			logger.info("请求微信的连接地址：" + url);
			Map<String, Object> jsonMap = JSON.parseObject(getJsonFromUrl(url, null, null), Map.class);
			logger.info(jsonMap.toString());
			if (jsonMap.get("errcode") == null || "0".equals(jsonMap.get("errcode"))) {
				// 静默方式请求，只获取用户openid
				return jsonMap.get("openid").toString();
			} else {
				logger.info("换取access_token错误：errcode：" + jsonMap.get("errcode") + ",errmsg：" + jsonMap.get("errmsg"));
			}
		}
		return null;
	}

	/**
	 * 换取token后，获得openid，去支付(支付的appId和secret)
	 * 
	 * @param code
	 *            微信回调返回的code
	 */
	@SuppressWarnings("unchecked")
	public static String getOpenidToPay(String code, String payAppId, String payAppSecret) {
		if (StringUtil.isNotNull(code)) {
			String url = String.format(exchangeTokenUrl, payAppId, payAppSecret, code);
			Map<String, Object> jsonMap = JSON.parseObject(getJsonFromUrl(url, null, null), Map.class);
			logger.info(jsonMap.toString());
			if (jsonMap.get("errcode") == null || "0".equals(jsonMap.get("errcode"))) {
				// 静默方式请求，只获取用户openid
				return jsonMap.get("openid").toString();
			} else {
				logger.info("=======换取access_token错误：errcode：" + jsonMap.get("errcode") + ",errmsg：" + jsonMap.get("errmsg"));
			}
		}
		return null;
	}
	
	/** 
     * JS权限验证配置
     * @param request 
     * @throws Exception 
     */  
    public static Map<String, String> getToken(String requestUrl, HttpServletRequest request) throws Exception {  
        String appid = SystemConfig.WEIXIN_GZH_APP_ID;
        String secret = SystemConfig.WEIXIN_GZH_APP_SECRET;
        String tokenKey = "access_token"+appid;
        String access_token = null;
        
        String ticketKey = "jsapi_ticket"+appid;
        logger.info("ticketKey:"+ticketKey);
        String jsapi_ticket = null;  
        if (null == RedisUtils.get(ticketKey)) {  
        	
        	// 第一步获取token存入全局缓存，  
            String result1 = HttpClientUtil.getHTTP("https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid=" + appid + "&secret=" + secret);  
            logger.info("返回result1："+result1);
            JSONObject obj1 = JSONObject.parseObject(result1);
            access_token = obj1.get("access_token").toString();  
        	
            // 第二步根据token得到jsapi_ticket存入全局缓存  
            String result2 = HttpClientUtil.getHTTP("https://api.weixin.qq.com/cgi-bin/ticket/getticket?access_token=" + access_token + "&type=jsapi");  
            logger.info("返回result2："+result2);
            JSONObject obj2 = JSONObject.parseObject(result2);
            jsapi_ticket = obj2.get("ticket").toString();  
            // 放入缓存，一小时
            RedisUtils.save(tokenKey, access_token, 3600);
            RedisUtils.save(ticketKey, jsapi_ticket, 3600);
        } else {  
            jsapi_ticket = String.valueOf(RedisUtils.get(ticketKey));
            logger.info("缓存中读取jsapi_ticket："+jsapi_ticket);
        }  
  
        // 获取请求的地址  
        StringBuffer url = request.getRequestURL();  
        String contextUrl = url.delete(url.length() - request.getRequestURI().length(), url.length()).toString();  
        String httpUrl = contextUrl + request.getRequestURI();  

        logger.info("httpUrl:"+ httpUrl);
        logger.info("requestUrl:"+ requestUrl);
        // 签名算法  
        Map<String, String> map = Sign.sign(jsapi_ticket, requestUrl);
        map.put("appId", appid);
        map.put("newDate", new Date().getTime() +"");
        return map;
    }  
    
    public static String getOnlyToken() throws Exception {  
    	String appid = SystemConfig.WEIXIN_GZH_APP_ID;
        String secret = SystemConfig.WEIXIN_GZH_APP_SECRET;
        String tokenKey = "access_token"+appid;
        String access_token = null;
        if (null == RedisUtils.get(tokenKey)) {  
            // 第一步获取token存入全局缓存，  
            String result1 = HttpClientUtil.getHTTP("https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid=" + appid + "&secret=" + secret);  
            logger.info("返回result1："+result1);
            JSONObject obj1 = JSONObject.parseObject(result1);
            access_token = obj1.get("access_token").toString();  
            // 放入缓存，一周
            RedisUtils.save(tokenKey, access_token, 60 * 60 * 24 * 7);
        } else {  
        	access_token = String.valueOf(RedisUtils.get(tokenKey));
        }  
        return access_token;  
    }
    
    /** 
     * 从微信上获取图片，上传至FTP
     * @param serverId 
     * @return 
     * @throws Exception 
     */  
    public static Map<String, String> downloadPic(String mediaId, String fileName, String filePath) {  
    	Map<String, String> map = new HashMap<String, String>();
    	String destPath = "";
    	BufferedInputStream in = null;
    	try {
    		String token = getOnlyToken();  
            String downloadUrl = "http://file.api.weixin.qq.com/cgi-bin/media/get?access_token="+token+"&media_id="+mediaId;  
            in = new BufferedInputStream(new URL(downloadUrl).openStream());  
            // 上传FTP
//            destPath = FtpUtil.upload(SystemConfig.FTP_PROJECT, in, fileName, "user", "img");
            destPath = SFTPUtil.upload(SystemConfig.FTP_PROJECT, in, fileName, "user", "img");
            map.put("code", "0");
            map.put("url", destPath);
			map.put("msg", "上传成功");
            logger.info("url====>" + destPath);  
		} catch (Exception e) {
			logger.error(e);
			map.put("code", "-1");
			map.put("msg", "上传失败");
		}finally {
			if(in !=null){
				try {
					in.close();
				} catch (IOException e) {
					logger.error(e);
				} 
			}
		}
        
        return map;  
    }  
      
//    public static byte[] imageToArray(String filePath) throws FileNotFoundException, IOException {  
//        byte[] data = null;  
//        FileImageInputStream input = null;  
//        try {  
//          input = new FileImageInputStream(new File(filePath));  
//          ByteArrayOutputStream output = new ByteArrayOutputStream();  
//          byte[] buf = new byte[1024];  
//          int numBytesRead = 0;  
//          while ((numBytesRead = input.read(buf)) != -1) {  
//          output.write(buf, 0, numBytesRead);  
//          }  
//          data = output.toByteArray();  
//          output.close();  
//          input.close();  
//        }  
//        catch (FileNotFoundException ex1) {  
//          ex1.printStackTrace();  
//        }  
//        catch (IOException ex1) {  
//          ex1.printStackTrace();  
//        }  
//        return data;  
//    }

}
